use crate::entities::category;
use crate::entities::category_translation;
use crate::errors::AppError;
use sea_orm::*;
use uuid::Uuid;

pub struct CategoryService;

impl CategoryService {
    pub async fn find_all_categories(
        db: &DatabaseConnection,
        language_code: Option<&str>,
    ) -> Result<Vec<category::Model>, AppError> {
        if let Some(lang) = language_code {
            let categories = category::Entity::find()
                .find_with_related(category_translation::Entity)
                .filter(category_translation::Column::LanguageCode.eq(lang))
                .all(db)
                .await?;
            Ok(categories.into_iter().map(|(cat, _)| cat).collect())
        } else {
            let categories = category::Entity::find().all(db).await?;
            Ok(categories)
        }
    }

    pub async fn find_category_by_id(
        db: &DatabaseConnection,
        id: Uuid,
        language_code: Option<&str>,
    ) -> Result<Option<(category::Model, Option<category_translation::Model>)>, AppError> {
        if let Some(lang) = language_code {
            let result = category::Entity::find_by_id(id)
                .find_with_related(category_translation::Entity)
                .filter(category_translation::Column::LanguageCode.eq(lang))
                .all(db)
                .await?;
            if let Some((category, translations)) = result.into_iter().next() {
                Ok(Some((category, translations.into_iter().next())))
            } else {
                Ok(None)
            }
        } else {
            let category = category::Entity::find_by_id(id).one(db).await?;
            Ok(category.map(|c| (c, None)))
        }
    }

    pub async fn create_category(
        db: &DatabaseConnection,
        category_data: category::ActiveModel,
    ) -> Result<category::Model, AppError> {
        let category = category_data.insert(db).await?;
        Ok(category)
    }

    pub async fn update_category(
        db: &DatabaseConnection,
        id: Uuid,
        category_data: category::ActiveModel,
    ) -> Result<Option<category::Model>, AppError> {
        // First check if the category exists
        let existing = category::Entity::find_by_id(id).one(db).await?;
        if existing.is_none() {
            return Ok(None);
        }
        
        // Update the category
        let category = category_data.update(db).await?;
        Ok(Some(category))
    }

    pub async fn delete_category(
        db: &DatabaseConnection,
        id: Uuid,
    ) -> Result<bool, AppError> {
        let result = category::Entity::delete_by_id(id).exec(db).await?;
        Ok(result.rows_affected > 0)
    }

    pub async fn create_category_translation(
        db: &DatabaseConnection,
        translation_data: category_translation::ActiveModel,
    ) -> Result<category_translation::Model, AppError> {
        let translation = translation_data.insert(db).await?;
        Ok(translation)
    }

    pub async fn update_category_translation(
        db: &DatabaseConnection,
        id: Uuid,
        translation_data: category_translation::ActiveModel,
    ) -> Result<Option<category_translation::Model>, AppError> {
        // First check if the translation exists
        let existing = category_translation::Entity::find_by_id(id).one(db).await?;
        if existing.is_none() {
            return Ok(None);
        }
        
        // Update the translation
        let translation = translation_data.update(db).await?;
        Ok(Some(translation))
    }

    pub async fn delete_category_translation(
        db: &DatabaseConnection,
        id: Uuid,
    ) -> Result<bool, AppError> {
        let result = category_translation::Entity::delete_by_id(id).exec(db).await?;
        Ok(result.rows_affected > 0)
    }

    pub async fn list_active(
        db: &DatabaseConnection,
        language_code: Option<&str>,
    ) -> Result<Vec<crate::models::Category>, AppError> {
        let categories = Self::find_all_categories(db, language_code).await?;
        Ok(categories.into_iter().map(|category| crate::models::Category {
            id: category.id,
            translations: vec![], // Will be populated by a separate query if needed
        }).collect())
    }
}